package lib.gameEngine.core{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.utils.getQualifiedSuperclassName;
	
	import game.common.prepare.Prepare;
	import game.data.constant.name.CoreName;
	import game.data.constant.name.NotificationName;
	
	import lib.gameEngine.common.data.Notification;
	
	/**
	 * Frame类为全局核心控制类，为单例对象。
	 * 
	 * 它拥有View,Controller,Model的引用。
	 * 
	 * 同时它也拥有全部通知的注册，由本类负责分发通知，及在相应的类上执行具体的某个通知。
	 * 
	 * 
	 * 
	 * 
	 * 
	 * @example 查看示例
	 * 
	 * <listing version="3.0"> 
	 * package{
	
			import flash.display.Sprite;
	
			import game.common.constant.NotificationName;
	
			import gameEngine.common.data.Notification;
			import gameEngine.core.Frame;
	
			public class FrameTest extends Sprite	{
		
				public function FrameTest(){
						var frame:Frame = Frame.getInstance();  //获取Frame实例
						frame.start(this);           //启动，同时进行预MVC结构的预注册
						frame.sendNotify(new Notification(NotificationName.LOAD)); //发送加载通知，此处需要注意的是，必须保证监听该通知的控制器或者视图已经被注册。
				}
			}
		}
		</listing> 
	 * 
	 * 
	 * 
	 *  
	 */
	public class Frame{
		
		private static var _self:Frame;   //单例对象
		
		private var _prepare:Prepare;
		
		private var _controllerPool:Object;  //控制器数据池
		private var _viewPool:Object;    //视图数据池
		private var _modelPool:Object;   //模型数据池
		private var _notifyPool:Object;  //通知数据池
		
		private var _sprite:Sprite;    //主舞台
		private var _mapLayer:Sprite;   //地图层
		private var _gameLayer:Sprite;  //游戏层
		private var _winLayer:Sprite;   //弹框层
		
		/**
		 * 构造函数
		 * 
		 *  
		 * @param single 利用包内类来生成单例对象，保证外部无法创建该对象
		 * 
		 */		
		public function Frame(single:Single){
			init();
		}
		
		/**
		 * Frame对象的单例方法
		 * 
		 *  
		 * @return Frame的单例
		 * 
		 */		
		public static function getInstance():Frame{
			if(!_self)_self = new Frame(new Single());
			return _self;
		}
		
/******************************************** public **************************************************/
		/**
		 * 启动函数，调用预注册类
		 * 
		 * 预注册类名称为Prepare，我们可以将一些需要在游戏启动之前注册完毕的Controller，View,Model的子类预先放入Prepare。
		 * 
		 * 一般来说，不需要存在太多的预注册对象。
		 * 
		 *  
		 * 
		 */
		public function start(sprite:Sprite):void{
			_prepare.register();
			setSprite(sprite);
			sendNotify(new Notification(NotificationName.LOAD));
		}
		
		/**
		 * 获取游戏主舞台
		 * 
		 *  
		 * @return 游戏主舞台
		 * 
		 */		
		public function getSprite():Sprite{
			return _sprite;
		}
		
		public function getMapLayer():Sprite{
			return _mapLayer;
		}
		
		public function getGameLayer():Sprite{
			return _gameLayer;
		}
		
		public function getWinLayer():Sprite{
			return _winLayer;
		}
		
		/**
		 * 注册Command
		 * 
		 *  
		 * @param command 控制器
		 * @param core 动作执行者
		 * 
		 */		
		public function registerController(controller:Controller,core:Core):void{
			if(!permissionCheck(core,2))return;
			saveController(controller);
			registerNotify(controller)
		}
		
		/**
		 * 获取控制器
		 * 
		 *  
		 * @param name 控制器名称
		 * @param core 动作执行者
		 * @return  控制器实例
		 * 
		 */		
		public function getController(name:String,core:Core):Controller{
			if(!permissionCheck(core,1))return null;
			return _controllerPool[name] as Controller;
		}
		
		/**
		 * 删除控制器
		 * 
		 *  
		 * @param name 控制器名称
		 * @param core 动作执行者
		 * 
		 */		
		public function deleteController(name:String,core:Core):void{
			if(!permissionCheck(core,3))return;
			_controllerPool[name].destory();
			delete _controllerPool[name];
		}
		
		/**
		 * 注册Model
		 * 
		 *  
		 * @param model 模型实例
		 * @param core 动作执行者
		 * 
		 */		
		public function registerModel(model:Model,core:Core):void{
			if(!permissionCheck(core,2))return;
			saveModel(model);
			//registerNotify(model);
		}
		
		/**
		 * 获取模型
		 * 
		 *  
		 * @param name 模型名称
		 * @param core 动作执行者
		 * @return  模型
		 * 
		 */		
		public function getModel(name:String,core:Core):Model{
			if(!permissionCheck(core,1))return null;
			return _modelPool[name] as Model;;
		}
		
		/**
		 * 删除模型
		 * 
		 *  
		 * @param name 模型名称
		 * @param core 动作执行者
		 * 
		 */		
		public function deleteModel(name:String,core:Core):void{
			if(!permissionCheck(core,3))return;
			_modelPool[name].destory();
			delete _modelPool[name];
		}
		
		/**
		 * 注册View
		 * 
		 *  
		 * @param view 视图实例
		 * @param core 动作执行者
		 * 
		 */		
		public function registerView(view:View,core:Core):void{
			if(!permissionCheck(core,2))return;
			saveView(view);
			registerNotify(view)
		}
		
		/**
		 * 获取View
		 * 
		 *  
		 * @param name 视图名称
		 * @param core 动作执行者
		 * @return 视图实例
		 * 
		 */		
		public function getView(name:String,core:Core):View{
			if(!permissionCheck(core,1))return null;
			return _viewPool[name] as View;
		}
		
		/**
		 * 删除视图
		 * 
		 *  
		 * @param name 视图名称
		 * @param core 动作执行者
		 * 
		 */		
		public function deleteView(name:String,core:Core):void{
			if(!permissionCheck(core,3))return;
			_viewPool[name].destory();
			delete _viewPool[name];
		}
		
		/**
		 * 发送通知
		 * 
		 *  
		 * @param notify 通知
		 * 
		 */		
		public function sendNotify(notify:Notification):void{
			var name:String = notify.getNotifyName();
			if(_notifyPool[name]){
				var array:Array = _notifyPool[name];
				for(var i:uint = 0; i < array.length; i++){
					var obj:Core = array[i];
					obj.getNotifyMap()[name](notify);
				}
			}
		}
		
		/**
		 * 删除指定通知
		 * 
		 *  
		 * @param name 通知名称
		 * @param core 动作执行者
		 * 
		 */		
		public function removeNotify(name:String,core:Core):void{
			var array:Array = _notifyPool[name];
			if(array){
				var index:uint = array.indexOf(core);
				array = array.splice(index,1);
				if(!array.length) delete _notifyPool[name];
			}
		}
			
		private function setSprite(sprite:Sprite):void{  //设置游戏主舞台
			_sprite = sprite;
			_sprite.stage.scaleMode = StageScaleMode.NO_SCALE;
			_sprite.stage.align = StageAlign.TOP_LEFT;
			layerInit();
		}
		
		
		private function init():void{  //初始化方法
			_notifyPool = new Object();
			_controllerPool = new Object();
			_viewPool = new Object();
			_modelPool = new Object();
			_prepare = new Prepare(this);
		}
		
		private function registerNotify(obj:Core):void{  //注册通知
			var notifyMap:Object = obj.getNotifyMap();
			for(var name:String in notifyMap){
				if(!_notifyPool[name]){
					_notifyPool[name] = [obj];
				}
				else{
					_notifyPool[name].push(obj);
				}
			}
		}
		
		private function saveController(controller:Controller):void{  //存储控制器
			if(nameCheck(controller))
			_controllerPool[controller.getName()] = controller;
		}
		
		private function saveView(view:View):void{  //存储视图
			if(nameCheck(view))
			_viewPool[view.getName()] = view;
		}
		
		private function saveModel(model:Model):void{  //存储模型
			if(nameCheck(model))
			_modelPool[model.getName()] = model;
		}
		
		private function permissionCheck(core:Core,flag:uint):Boolean{  
			//权限判断  flag为动作标志  1：获取  2注册  3删除
			//控制器能够进行获取，注册，删除等操作
			//视图只能进行注册和获取操作
			//模型不能进行注册，删除和获取
			var type:String = getQualifiedSuperclassName(core).split("::")[1];
			var weight:uint = 0 ; //权重
			switch(type){
				case "Controller":
					weight = 4;
					break;
				case "View":
					weight = 3;
					break;
				default:
					weight = 0;
					break;
			}
			if(core.getName() == CoreName.PREPARE)weight = 4;  //特权处理，优先在Prepare中处理的优先级设置为最高
			return weight > flag;
		}
		
		private function nameCheck(core:Core):Boolean{  //名称判断
			var pool:Object;
			var type:String = getQualifiedSuperclassName(core).split("::")[1];
			switch(type){
				case "Controller":
					pool = _controllerPool;
					break;
				case "View":
					pool = _viewPool;
					break;
				case "Model":
					pool = _modelPool;
					break;
			}	
			if(pool[core.getName()]){
			//	Logger.waring("已存在名为"+ core.getName() + "的" + type);
				return false;
			}
			return true;
		}
		
		private function layerInit():void{
			_mapLayer = new Sprite();
			_gameLayer = new Sprite();
			_winLayer = new Sprite();
			_sprite.addChild(_mapLayer);
			_sprite.addChild(_gameLayer);
			_sprite.addChild(_winLayer);
			_mapLayer.mouseEnabled = false;
			_gameLayer.mouseEnabled = false;
			_winLayer.mouseEnabled = false;
			_sprite.mouseEnabled = false;  //禁用鼠标事件
		}
	}
}

class Single{}